package edu.mse.camel.client.posterboard.ui.adapters;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartFactory;

import com.cea.papyrus.diagram.activity.ActivityDiagramGraphicalEditPartsFactory;
import com.cea.papyrus.diagram.classdiagram.ClassDiagramGraphicalEditPartsFactory;
import com.cea.papyrus.diagram.sequence.sedi.edit.SeDiEditPartFactory;
import com.cea.papyrus.diagram.statemachine.StateMachineGraphicalEditPartsFactory;
import com.cea.papyrus.diagram.usecase.UseCaseDiagramGraphicalEditPartsFactory;
import com.cea.papyrus.diagraminterchange2.di2.DiConstants;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;

import edu.mse.camel.client.posterboard.posterboard.PBDiagram;
import edu.mse.camel.client.posterboard.ui.editor.PosterBoardModelManager;
import edu.mse.camel.client.posterboard.ui.editpart.AdaptedActivityDiagramEditpart;
import edu.mse.camel.client.posterboard.ui.editpart.AdaptedClassDiagramEditpart;
import edu.mse.camel.client.posterboard.ui.editpart.AdaptedSequenceDiagramEditpart;
import edu.mse.camel.client.posterboard.ui.editpart.AdaptedStateMachineDiagramEditpart;
import edu.mse.camel.client.posterboard.ui.editpart.AdaptedUsecaseDiagramEditpart;

public class UMLToolAdapter implements IToolAdapter {
	
	// make protected
	protected UMLToolAdapter() {
		
	}
	
	private Map<Class<?>, EditPartFactory> factories;
	
	private PosterBoardModelManager pbModelManager;
	
	public static UMLToolAdapter INSTANCE = new UMLToolAdapter();
	
	public void initialize(PosterBoardModelManager pbModelManager) {
		this.pbModelManager = pbModelManager;
		init();
	}
	
	private void init() {
		factories = new HashMap<Class<?>, EditPartFactory>();
		factories.put(
				AdaptedClassDiagramEditpart.class,
				new ClassDiagramGraphicalEditPartsFactory(pbModelManager.getPapyrusModelManager()));
		factories.put(
				AdaptedActivityDiagramEditpart.class,
				new ActivityDiagramGraphicalEditPartsFactory(pbModelManager.getPapyrusModelManager()));
		factories.put(
				AdaptedSequenceDiagramEditpart.class,
				new SeDiEditPartFactory(pbModelManager.getPapyrusModelManager()));
		factories.put(
				AdaptedUsecaseDiagramEditpart.class,
				new UseCaseDiagramGraphicalEditPartsFactory(pbModelManager.getPapyrusModelManager()));
		factories.put(
				AdaptedStateMachineDiagramEditpart.class,
				new StateMachineGraphicalEditPartsFactory(pbModelManager.getPapyrusModelManager()));
		
	}

	/* (non-Javadoc)
	 * @see edu.mse.camel.client.posterboard.ui.util.IToolAdapter#getAdaptedDiagramEditpart(edu.mse.camel.client.posterboard.posterboard.PBDiagram)
	 */
	public EditPart getAdaptedDiagramEditpart(PBDiagram model) {
		Diagram d = (Diagram) model.getDelegate();
		if (d.getType().equals(DiConstants.CLASS_DIAGRAM)) {
			AdaptedClassDiagramEditpart part = 
				new AdaptedClassDiagramEditpart(model, pbModelManager.getPapyrusModelManager());
			return part;
		}
		if (d.getType().equals(DiConstants.ACTIVITY_DIAGRAM)) {
			AdaptedActivityDiagramEditpart part =
				new AdaptedActivityDiagramEditpart(model, pbModelManager.getPapyrusModelManager());
			return part;
		}
		if (d.getType().equals(DiConstants.SEQUENCE_DIAGRAM)) {
			AdaptedSequenceDiagramEditpart part =
				new AdaptedSequenceDiagramEditpart(model, pbModelManager.getPapyrusModelManager());
			return part;
		}
		if (d.getType().equals(DiConstants.USE_CASE_DIAGRAM)) {
			AdaptedUsecaseDiagramEditpart part = 
				new AdaptedUsecaseDiagramEditpart(model, pbModelManager.getPapyrusModelManager());
			return part;
		}
		if (d.getType().equals(DiConstants.STATE_MACHINE_DIAGRAM)) {
			AdaptedStateMachineDiagramEditpart part = 
				new AdaptedStateMachineDiagramEditpart(model, pbModelManager.getPapyrusModelManager());
			return part;
		}
		return null;
	}
	
	/* (non-Javadoc)
	 * @see edu.mse.camel.client.posterboard.ui.util.IToolAdapter#getEditPartFactory(java.lang.String)
	 */
	public EditPartFactory getEditPartFactory(String diagramType) {
		if (diagramType.equals(DiConstants.CLASS_DIAGRAM)) {
			return factories.get(AdaptedClassDiagramEditpart.class);
		}
		if (diagramType.equals(DiConstants.ACTIVITY_DIAGRAM)) {
			return factories.get(AdaptedActivityDiagramEditpart.class);
		}
		if (diagramType.equals(DiConstants.SEQUENCE_DIAGRAM)) {
			return factories.get(AdaptedSequenceDiagramEditpart.class);
		}
		if (diagramType.equals(DiConstants.USE_CASE_DIAGRAM)) {
			return factories.get(AdaptedSequenceDiagramEditpart.class);
		}
		if (diagramType.equals(DiConstants.STATE_MACHINE_DIAGRAM)) {
			return factories.get(AdaptedStateMachineDiagramEditpart.class);
		}
		return null;
	}
	
	/* (non-Javadoc)
	 * @see edu.mse.camel.client.posterboard.ui.util.IToolAdapter#getEditPartFactory(org.eclipse.gef.EditPart)
	 */
	public EditPartFactory getEditPartFactory(EditPart context) {
		while (!isValidEditpart(context)) {
			context = context.getParent();
		}
		return factories.get(context.getClass());
	}
	
	private boolean isValidEditpart(EditPart ePart) {
		if (ePart.getClass().equals(AdaptedClassDiagramEditpart.class) 
			|| ePart.getClass().equals(AdaptedActivityDiagramEditpart.class)
			|| ePart.getClass().equals(AdaptedSequenceDiagramEditpart.class)
			|| ePart.getClass().equals(AdaptedUsecaseDiagramEditpart.class)
			|| ePart.getClass().equals(AdaptedStateMachineDiagramEditpart.class)) {
			return true;
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see edu.mse.camel.client.posterboard.ui.util.IToolAdapter#shouldSetDelegate(org.eclipse.gef.EditPart, org.eclipse.gef.EditPartFactory)
	 */
	public boolean shouldSetDelegate(EditPart context, EditPartFactory delegate) {
		 return !delegate.getClass().equals(factories.get(context.getClass()));
	}

	public boolean isSupported(String diagramType) {
		if (diagramType.equals(DiConstants.CLASS_DIAGRAM)
				|| diagramType.equals(DiConstants.ACTIVITY_DIAGRAM)
				|| diagramType.equals(DiConstants.USE_CASE_DIAGRAM)
				|| diagramType.equals(DiConstants.STATE_MACHINE_DIAGRAM)
				|| diagramType.equals(DiConstants.SEQUENCE_DIAGRAM)) {
			return true;
		}
		return false;
	}

}
